# -*- coding: utf-8 -*-
from MyApi import *
import thosttraderapi as api
import os



class CTradeSpi(api.CThostFtdcTraderSpi):
	myapi=''
	def __init__(self,myapi):
		api.CThostFtdcTraderSpi.__init__(self)
		self.myapi=myapi

		
	def OnFrontConnected(self) -> "void":
		self.myapi.mylog.info("receive OnFrontConnected")
		self.myapi.ctlevent.set()

	def OnRspAuthenticate(self, pRspAuthenticateField: 'CThostFtdcRspAuthenticateField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":	
		PrintReName("OnRspAuthenticate", self.myapi.mylog)
		if(pRspInfo.ErrorID == 0):
			PrintReMsg(pRspInfo, self.myapi.mylog)
			self.myapi.ctlevent.set()
		else:
			PrintReMsg(pRspInfo, self.myapi.mylog)
			os._exit(233)
		
	def OnRspUserLogin(self, pRspUserLogin: 'CThostFtdcRspUserLoginField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		PrintReName("OnRspUserLogin", self.myapi.mylog)
		if(pRspInfo.ErrorID == 0):
			PrintReMsg(pRspInfo, self.myapi.mylog)
			self.myapi.ctlevent.set()
		else:
			PrintReMsg(pRspInfo, self.myapi.mylog)
			os._exit(233)
		

	def OnRspQryDepthMarketData(self, pDepthMarketData: 'CThostFtdcDepthMarketDataField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		mdlist=[pDepthMarketData.TradingDay,\
			pDepthMarketData.InstrumentID,\
			pDepthMarketData.ExchangeID,\
			pDepthMarketData.ExchangeInstID,\
			pDepthMarketData.LastPrice,\
			pDepthMarketData.PreSettlementPrice,\
			pDepthMarketData.PreClosePrice,\
			pDepthMarketData.PreOpenInterest,\
			pDepthMarketData.OpenPrice,\
			pDepthMarketData.HighestPrice,\
			pDepthMarketData.LowestPrice,\
			pDepthMarketData.Volume,\
			pDepthMarketData.Turnover,\
			pDepthMarketData.OpenInterest,\
			pDepthMarketData.ClosePrice,\
			pDepthMarketData.SettlementPrice,\
			pDepthMarketData.UpperLimitPrice,\
			pDepthMarketData.LowerLimitPrice,\
			pDepthMarketData.PreDelta,\
			pDepthMarketData.CurrDelta,\
			pDepthMarketData.UpdateTime,\
			pDepthMarketData.UpdateMillisec,\
			pDepthMarketData.ActionDay,\
			pDepthMarketData.BandingUpperPrice,\
			pDepthMarketData.BandingLowerPrice,\
		]
		DealTooMax(mdlist)
		self.myapi.mddata.append(mdlist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()

	def OnRspQryClassifiedInstrument(self, pInstrument: 'CThostFtdcInstrumentField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		inslist=[pInstrument.InstrumentID,\
			pInstrument.ExchangeID,\
			pInstrument.InstrumentName,\
			pInstrument.ExchangeInstID,\
			pInstrument.ProductID,\
			pInstrument.ProductClass,\
			pInstrument.DeliveryYear,\
			pInstrument.DeliveryMonth,\
			pInstrument.MaxMarketOrderVolume,\
			pInstrument.MinMarketOrderVolume,\
			pInstrument.MaxLimitOrderVolume,\
			pInstrument.MinLimitOrderVolume,\
			pInstrument.VolumeMultiple,\
			pInstrument.PriceTick,\
			pInstrument.CreateDate,\
			pInstrument.OpenDate,\
			pInstrument.ExpireDate,\
			pInstrument.StartDelivDate,\
			pInstrument.EndDelivDate,\
			pInstrument.InstLifePhase,\
			pInstrument.IsTrading,\
			pInstrument.PositionType,\
			pInstrument.PositionDateType,\
			pInstrument.LongMarginRatio,\
			pInstrument.ShortMarginRatio,\
			pInstrument.MaxMarginSideAlgorithm,\
			pInstrument.UnderlyingInstrID,\
			pInstrument.StrikePrice,\
			pInstrument.OptionsType,\
			pInstrument.UnderlyingMultiple,\
			pInstrument.CombinationType,\
		]
		#print(inslist[0], inslist[19], inslist[28])
		DealTooMaxIns(inslist)
		#print(inslist[0], inslist[19], inslist[28])
		self.myapi.insdata.append(inslist)
		if(bIsLast == True):
			self.myapi.ctlevent.set()

	def OnRspQryInstrument(self, pInstrument: 'CThostFtdcInstrumentField',pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
		print(pInstrument.ExchangeID, pInstrument.InstrumentID, pInstrument.IsTrading)
		if(bIsLast == True):
			self.myapi.ctlevent.set()


#static function
#print errormsg
def PrintReMsg(pRspInfo, mylog):
	if pRspInfo is not None:
		remsg = "ErrorID= " + str(pRspInfo.ErrorID) + " ErrorMsg= " + str(pRspInfo.ErrorMsg)
		mylog.info(remsg)
	else:
		mylog.info("ErrorID= null ErrorMsg= null")
		return 1

#print func name
def PrintReName(rename, mylog):
	remsg = "receive" + rename
	mylog.info(remsg)


#deal with Max-number in marketdata
def DealTooMax(mdlist):
	maxprice = 1e+15
	minprice = -1e+15
	coldict={"LastPrice": [4, 0.0, 3],\
		  "PreSettlementPrice": [5, 0.0, 3],\
		  "PreClosePrice": [6, 0.0, 3],\
		  "PreOpenInterest": [7, 0.0, 3],\
		  "OpenPrice": [8, "", 3],\
		  "HighestPrice": [9, "", 3],\
		  "LowestPrice": [10, "", 3],\
		  "Volume": [11, 0, 3],\
		  "Turnover": [12, 0.0, 3],\
		  "OpenInterest": [13, 0.0, 3],\
		  "ClosePrice": [14, 0.0, 3],\
		  "SettlementPrice": [15, 0.0, 3],\
		  "UpperLimitPrice": [16, 0.0, 3],\
		  "LowerLimitPrice": [17, 0.0, 3],\
		  "PreDelta": [18, "", 8],\
		  "CurrDelta": [19, "", 8],\
		  "BandingUpperPrice": [23, "", 3],\
		  "BandingLowerPrice": [24, "", 3]} 
	for colname in coldict.keys():
		indexnum=coldict[colname][0]
		defaultvalue=coldict[colname][1]
		roundtype=coldict[colname][2]
		if(mdlist[indexnum] > maxprice or mdlist[indexnum] < minprice): 
			mdlist[indexnum] = defaultvalue
		else:
			mdlist[indexnum] = round(mdlist[indexnum], roundtype)


#deal with Max-number and nullchar in instrument
def DealTooMaxIns(inslist):
	maxprice = 1e+15
	minprice = -1e+15
	'''
	coldict={\
		"InstLifePhase": [19, "", 3],\
		"PositionType": [21, "", 3],\
		"PositionDateType": [22, "", 3],\
		"LongMarginRatio": [23, "", 3],\
		"ShortMarginRatio": [24, "", 3],\
		"MaxMarginSideAlgorithm": [25, "", 3],\
		"StrikePrice" : [27, "", 3],\
		"OptionsType": [28, "", 3],\
		"UnderlyingMultiple": [29, "", 3],\
		"CombinationType": [30, "", 3]} 
	'''
	intcoldict={\
		"LongMarginRatio": [23, "", 3],\
		"ShortMarginRatio": [24, "", 3],\
		"StrikePrice" : [27, "", 3],\
		"UnderlyingMultiple": [29, "", 3],\
		} 
	for colname in intcoldict.keys():
		#print(colname)
		indexnum=intcoldict[colname][0]
		defaultvalue=intcoldict[colname][1]
		roundtype=intcoldict[colname][2]
		if(inslist[indexnum] > maxprice or inslist[indexnum] < minprice): 
			inslist[indexnum] = defaultvalue
		else:
			inslist[indexnum] = round(inslist[indexnum], roundtype)
	strcoldic={\
		"InstLifePhase": [19, ""],\
		"PositionType": [21, ""],\
		"PositionDateType": [22, ""],\
		"MaxMarginSideAlgorithm": [25, ""],\
		"OptionsType": [28, ""],\
		"UnderlyingMultiple": [29, ""],\
		"CombinationType": [30, ""],\
	}
	for colname in strcoldic.keys():
		indexnum=strcoldic[colname][0]
		defaultvalue=strcoldic[colname][1]
		if(inslist[indexnum] == '\x00'):
			inslist[indexnum] = defaultvalue
